#include "znx_file.h"

int64_t
znx_read_file(const char *file, u_char *buf,
    size_t buf_size, char **err)
{
    int                         fd;
    znx_result_t                ret;
    znx_file_stat_t             stat;
    size_t                      file_size;

    ret = znx_syscall_open_nomode(file, O_RDONLY);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        return -1;
    }

    fd = (int)ret;

    ret = znx_syscall_file_fstat(fd, &stat);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        goto failed;
    }

    file_size = (size_t)stat.st_size;
    if (buf_size < file_size) {
        *err = "buf size is too small";
        goto failed;
    }

    ret = znx_syscall_read(fd, buf, file_size);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        goto failed;
    }

    return ret;

failed:
    znx_syscall_close(fd);
    return -1;
}


znx_bool_t
znx_file_load(znx_pool_t *pool,
    const char *file, znx_str_t *buffer, char **err)
{
    znx_result_t            ret;
    int                     fd = INVALID_FD;
    znx_file_stat_t         stat;

    ret = znx_syscall_open_nomode(file, O_RDONLY);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        return ZNX_FALSE;
    }

    fd = (int)ret;

    ret = znx_syscall_file_fstat(fd, &stat);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        znx_syscall_close(fd);
        return ZNX_FALSE;
    }

    if (stat.st_size == 0) {
        buffer->data = NULL;
        buffer->len = 0;
        znx_syscall_close(fd);
        return ZNX_SUCCESS;
    }

    buffer->data = znx_pool_malloc(pool, (size_t)stat.st_size);

    ret = znx_syscall_read(fd, buffer->data, (size_t)stat.st_size);
    if (ret < 0) {
        *err = strerror((int)(-ret));
        znx_syscall_close(fd);
        return ZNX_FALSE;
    }

    if ((size_t)ret != (size_t)stat.st_size) {
        *err = "the file may be modify in load operation";
        znx_syscall_close(fd);
        return ZNX_FALSE;
    }

    buffer->len = (size_t)stat.st_size;
    znx_syscall_close(fd);

    return ZNX_TRUE;
}


